from fastapi import APIRouter, HTTPException, Request, BackgroundTasks
from app.models.project import ProjectConfig, GenerationResponse
from app.core.generator import create_project_structure
import json
import os
import shutil
import tempfile
from uuid import uuid4
from pydantic import ValidationError
from fastapi.responses import FileResponse

router = APIRouter()

@router.post("/generate-project", response_model=GenerationResponse)
async def generate_project(request: Request):
    """
    生成项目的主要API端点。直接读取请求体并用 Pydantic 验证，兼容旧字段名。
    """
    try:
        body = await request.json()

        # 兼容老客户端：如果请求中包含 targetPlatforms（数组），取第一个值赋给 targetPlatform
        if isinstance(body, dict) and 'targetPlatforms' in body and isinstance(body.get('targetPlatforms'), list):
            first = body.get('targetPlatforms')[0] if len(body.get('targetPlatforms')) > 0 else None
            if first:
                body['targetPlatform'] = first

        # 用 Pydantic 验证并转换为模型
        try:
            config = ProjectConfig(**body)
        except ValidationError as ve:
            raise HTTPException(status_code=422, detail=ve.errors())

        # 调用生成器创建项目结构
        project_path = create_project_structure(config)

        return GenerationResponse(
            message="项目生成成功！",
            project_path=project_path
        )
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/download-project/{project_name}")
async def download_project(project_name: str, background_tasks: BackgroundTasks):
    """将生成的项目打包为 zip 并返回给前端下载"""

    base_dir = os.path.join(os.path.dirname(__file__), "../../../../generated_projects")
    project_dir = os.path.join(base_dir, project_name)

    if not os.path.isdir(project_dir):
        raise HTTPException(status_code=404, detail="指定的项目不存在，请先生成项目")

    temp_base = os.path.join(tempfile.gettempdir(), f"{project_name}-{uuid4().hex}")

    archive_path = shutil.make_archive(
        temp_base,
        'zip',
        root_dir=os.path.dirname(project_dir),
        base_dir=os.path.basename(project_dir)
    )

    def remove_file(path: str):
        try:
            if os.path.exists(path):
                os.remove(path)
        except OSError:
            pass

    background_tasks.add_task(remove_file, archive_path)

    return FileResponse(
        archive_path,
        media_type='application/zip',
        filename=f"{project_name}.zip"
    )

@router.get("/base-components/{framework}")
async def get_base_components(framework: str):
    """
    根据UI框架获取可选的基础组件列表。
    """
    try:
        # 读取配置文件（支持通过环境变量覆盖路径）
        env_config_path = os.getenv("PROJECT_TYPES_CONFIG")
        if env_config_path and os.path.isfile(env_config_path):
            config_path = env_config_path
        else:
            # 优先使用容器工作目录下的 /app/config，回退到源码相对路径
            candidate_paths = [
                os.path.join("/app", "config", "project_types.json"),
                os.path.join(os.getcwd(), "config", "project_types.json"),
                os.path.join(os.path.dirname(__file__), "../../../../config/project_types.json"),
            ]
            config_path = next((p for p in candidate_paths if os.path.isfile(p)), candidate_paths[-1])
        with open(config_path, "r", encoding="utf-8") as f:
            config_data = json.load(f)
        
        # 获取指定框架的基础组件
        frameworks = config_data.get("ui_frameworks", {})
        if framework not in frameworks:
            raise HTTPException(status_code=404, detail=f"框架 '{framework}' 不存在")
        
        base_components = frameworks[framework].get("base_components", [])
        
        return {
            "framework": framework,
            "components": base_components
        }
    except FileNotFoundError:
        raise HTTPException(status_code=500, detail="配置文件未找到，请确认容器内是否存在 /app/config/project_types.json，或设置环境变量 PROJECT_TYPES_CONFIG 指向正确路径")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
